package com.phpxiu.app.view;

import android.Manifest;
import android.app.Dialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.AnimationDrawable;
import android.hardware.Camera;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.google.gson.Gson;
import com.phpxiu.app.api.OnDialogClickListener;
import com.phpxiu.app.api.OnRoomPayListener;
import com.phpxiu.app.config.Constants;
import com.phpxiu.app.config.HttpConfig;
import com.phpxiu.app.controller.avcontroller.QavsdkControl;
import com.phpxiu.app.kkylive.KKYApp;
import com.phpxiu.app.kkylive.R;
import com.phpxiu.app.model.CurLiveInfo;
import com.phpxiu.app.model.LiveRoomInfo;
import com.phpxiu.app.model.MsgSender;
import com.phpxiu.app.model.MySelfInfo;
import com.phpxiu.app.model.ShareContent;
import com.phpxiu.app.model.event.OnForceLogoutEvent;
import com.phpxiu.app.model.event.OnUpdateBalance;
import com.phpxiu.app.model.event.OnVideoShow;
import com.phpxiu.app.model.event.WeiXinEvent;
import com.phpxiu.app.model.gift.Gift;
import com.phpxiu.app.model.msg.EnterMsg;
import com.phpxiu.app.model.msg.MultiVideoMsg;
import com.phpxiu.app.model.response.LiveEndModel;
import com.phpxiu.app.model.response.LiveRoomMode;
import com.phpxiu.app.model.response.MsgModel;
import com.phpxiu.app.model.response.RoomPayModel;
import com.phpxiu.app.okhttp.OKHttp;
import com.phpxiu.app.okhttp.OKHttpResponseModel;
import com.phpxiu.app.okhttp.handler.OKHttpUIHandler;
import com.phpxiu.app.okhttp.param.OKHttpParam;
import com.phpxiu.app.presenters.EnterQuitePresenter;
import com.phpxiu.app.presenters.RoomPresenter;
import com.phpxiu.app.presenters.viewinterface.EnterQuiteRoomView;
import com.phpxiu.app.presenters.viewinterface.RoomView;
import com.phpxiu.app.utils.KKYUtil;
import com.phpxiu.app.view.custom.FrescoImageView;
import com.phpxiu.app.view.dialog.LiveResultDialog;
import com.phpxiu.app.view.dialog.LiveRoomWin;
import com.phpxiu.app.view.dialog.RoomCoverDialog;
import com.tencent.TIMElem;
import com.tencent.TIMElemType;
import com.tencent.TIMGroupSystemElem;
import com.tencent.TIMGroupSystemElemType;
import com.tencent.TIMMessage;
import com.tencent.TIMTextElem;
import com.tencent.TIMValueCallBack;
import com.tencent.av.TIMAvManager;
import com.tencent.av.sdk.AVView;
import com.tencent.bugly.imsdk.crashreport.CrashReport;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

import de.greenrobot.event.EventBus;
import de.greenrobot.event.Subscribe;


/**
 * Live直播类
 */
public class RoomVideoRoom extends BaseShare implements EnterQuiteRoomView, RoomView, View.OnClickListener,OnRoomPayListener{
    private static final String TAG ="LiveVideoRoom";
    private static final int TIMEOUT_RESPONSE=0x1;//连麦应答超时
    private static final int REFRESH_JOIN_REQ=0x2;//为防止没有收到应答消息，刷新可连麦状态
    private static final int COUNT_DOWN_START=0x4;//倒计时开始
    private static final int HIDE_COUNT_DOWN_VIEW=0x5;//隐藏倒计时视图
    private static final int ADD_VIDEO_REQUEST=0x6;//添加连麦请求者
    private static final int DEL_VIDEO_REQUEST=0x7;//删除请求连麦请求者
    public final static int REQUEST_CODE_ASK_PERMISSIONS = 0x66;//检测权限
    private final static int SHOW_ROOM_PAY=0x77;//检测房间扣费
    private final static int ROOM_PAY_EXCUTE=0x78;//房间扣费
    private final static long PAY_PERIOD=60*1000;//扣费周期
    private final static int REQUEST_PAY_RECHARGE=0x79;//请求充值
    public  static final boolean DEBUG_INTERACT=false;//调试连麦流程
    public static final String [] AV_PERMISSION={
            Manifest.permission.RECORD_AUDIO,//录音
            Manifest.permission.CAMERA//摄像头
    };
    private String[] friendIds;
    private String liveType="0";
    private EnterQuitePresenter mEnterRoomHelper;
    public RoomPresenter mRoomPresenter;
    private View avView;
    private Dialog hostInteractDlg;//主播端连麦请求应答对话框
    private Dialog hostCancelInteractDlg;//主播关闭取消某个互动视频对话框
    private TextView memberInteractInfo;//连麦请求对话框描述信息
    private String interactInfoFormat;
    private FrescoImageView interactMemberHeadView;
    private TextView interactMemberNick;

    private boolean isShowResult=false;//是否显示观看直播的结果，用于判断是否为主播结束直播被动退出
    private int memberVideoCount = 0;//已收到连麦的请求个数，最多三个，第四个请求忽略，不应答
    private ConcurrentHashMap<String,MsgSender> interactMembers=new ConcurrentHashMap<String,MsgSender>();//连麦成员组
    private static CustomExceptionHandler mCrashHandler;

    private Timer heartBeatTimer;
    private HeartBeatTask heartBeatTask;
    private long liveStartTime=System.currentTimeMillis();//开播时间
    private long liveTotalTime=0;//开播时长

    private LiveResultDialog resultDialog;

    private LiveRoomWin win;
    private OKHttpParam heartParam;
    public AtomicLong watchCount=new AtomicLong(0L);//观看人数

    private AtomicLong mOnlineCount;//在线人数

    private boolean isInitReportOnlineCount=false;//是否已初始化上报的人数


    public ShareContent roomShareContent=null;//房间分享内容
    private RelativeLayout coverView;
    private ImageView loadView;
    private AnimationDrawable loadAniDraw;
    private FrescoImageView coverImage;
    private int count=3;//倒计时总数
    private Animation countDownAnim;
    private TextView countView;

    private TextView liveExtraView;//房间号等信息
    private boolean isForceLoginOut=false;//账号多终端登录被踢
    private MsgSender mMsgSender;

    private Dialog multiVideoStateDlg;//连麦状态(成员端显示)对话框，玩家请求后显示等待状态，主播响应为否定后，提示
    private TextView multiVideoStateView;
    private String waitHostResponseMsg;

    private MsgModel msgModel;
    private EnterMsg enterMsg;
    private Gson gson=new Gson();

    private String roomLiveNo;//直播编号
    private String[] recordIds;//视频录制ids

    private RoomCoverDialog payDialog;
    private int rate=0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        switchLanguage();
        friendIds=getIntent().getStringArrayExtra(PublishLive.EXTRA_FRIEND_IDS);
        liveType=getIntent().getStringExtra(PublishLive.EXTRA_LIVE_TYPE);
        if(liveType==null||"".equals(liveType)){
            liveType="0";
        }
        CurLiveInfo.isInRoom=true;
        isForceLoginOut=false;
        mMsgSender =new MsgSender();
        mMsgSender.setUid(MySelfInfo.getInstance().getId());
        mMsgSender.setAvatar(MySelfInfo.getInstance().getAvatar());
        mMsgSender.setNickname(MySelfInfo.getInstance().getNickName());
        EventBus.getDefault().register(this);
        mCrashHandler = new CustomExceptionHandler();
        Thread.currentThread().setUncaughtExceptionHandler(mCrashHandler);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//不锁屏
        registerReceiver();
        setContentView(R.layout.live_video_room);
        try {
            initView();
        }catch (NullPointerException e){
            finish();
            return;
        }
        //进出房间的协助类
        mEnterRoomHelper = new EnterQuitePresenter(this, this);
        mEnterRoomHelper.setLiveParams(liveType,friendIds);
        //房间内的交互协助类
        mRoomPresenter = new RoomPresenter(this, this);
        if(QavsdkControl.getInstance().getAVContext()==null){
            if(MySelfInfo.getInstance().getIdStatus()== Constants.HOST) {
               //KKYUtil.tip(this, "创建房间失败!", Gravity.CENTER).show();
               CrashReport.postCatchedException(new Throwable("create Room failed：QavsdkControl.getInstance().getAVContext()==null"));
            }else{
                //KKYUtil.tip(this,"进入房间失败!",Gravity.CENTER).show();
                CrashReport.postCatchedException(new Throwable("enter Room failed：QavsdkControl.getInstance().getAVContext()==null"));
            }
            finish();
            return;
        }
        //进入房间流程
        mEnterRoomHelper.startEnterRoom();
        mRoomPresenter.setCameraPreviewChangeCallback();
        if(MySelfInfo.getInstance().getIdStatus()== Constants.MEMBER){//观众实例
            int a = ContextCompat.checkSelfPermission(this, AV_PERMISSION[0]);
            if (a != PackageManager.PERMISSION_GRANTED) {//未授权的权限
                ActivityCompat.requestPermissions(this, new String[]{AV_PERMISSION[0]}, REQUEST_CODE_ASK_PERMISSIONS);
            }
            int v = ContextCompat.checkSelfPermission(this, AV_PERMISSION[1]);
            if (v != PackageManager.PERMISSION_GRANTED) {//未授权的权限
                ActivityCompat.requestPermissions(this, new String[]{AV_PERMISSION[1]}, REQUEST_CODE_ASK_PERMISSIONS);
            }
        }
        mOnlineCount=new AtomicLong(0L);
        try {
            for (Gift g: KKYApp.getInstance().GIFTS){
                g.setSelected(false);
            }
        }catch (NullPointerException e){
            e.printStackTrace();
        }
        resultDialog=new LiveResultDialog(this);
        roomShareContent=new ShareContent(RoomVideoRoom.this);
        roomShareContent.setTitle(CurLiveInfo.getHostName());
        roomShareContent.setSummary(CurLiveInfo.getHostName());
        roomShareContent.setImageUrl(CurLiveInfo.getHostAvator());
        roomShareContent.setTargetUrl(HttpConfig.SHARE_URL+ CurLiveInfo.getHostID());
        resultDialog.getWindow().getAttributes().width=(int) KKYApp.getInstance().screenWidth;
        resultDialog.getWindow().getAttributes().height=(int) KKYApp.getInstance().screenHeight;
    }

    /**
     * 匹配语言
     */
    private void switchLanguage(){
        SharedPreferences sp=getSharedPreferences(UserSetting.KKY_USER_LANGUAGE_CONFIG,MODE_PRIVATE);
        int code=sp.getInt(UserSetting.KKY_CURRENT_LANGUAGE_CODE,0);
        Resources resources =getResources();//获得res资源对象
        Configuration config = resources.getConfiguration();//获得设置对象
        DisplayMetrics dm = resources.getDisplayMetrics();//获得屏幕参数：主要是分辨率，像素等。
        switch (code){
            case 1:
                config.locale = Locale.SIMPLIFIED_CHINESE; //简体中文
                break;
            case 2:
                config.locale = Locale.ENGLISH;
                break;
            default:
                config.locale= Locale.getDefault();
                break;
        }
        resources.updateConfiguration(config, dm);
    }


    @Subscribe
    public void videoShow(OnVideoShow show){
        if(coverView==null||coverView.getVisibility()!=View.VISIBLE){
            return;
        }
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if(loadAniDraw!=null){
                    loadAniDraw.stop();
                }
                coverView.setVisibility(View.INVISIBLE);

            }
        });
    }

    /**
     * 微信分享完毕
     */
    @Subscribe
    public void onWXShare(WeiXinEvent event){
        if(WeiXinEvent.SHARE==event.getCode()){
            onPlatformShareBack(PLATFORM_WX);
        }
    }

    /**
     * 强制下线事件
     */
    @Subscribe
    public void onForceLogOut(OnForceLogoutEvent event){
        if(mRoomPresenter!=null){
            isForceLoginOut=true;
            mRoomPresenter.prepareQuitRoom(false);
        }
    }

    /**
     * 初始化界面
     */
    private void initView() {
        liveExtraView=(TextView)findViewById(R.id.live_extra_info_view);
        if (MySelfInfo.getInstance().getIdStatus() == Constants.HOST) {
            initHostInteractDlg();
            initHostCancelInteractDlg();
        }else{
            initMultiVideoStateDlg();
        }
        avView = findViewById(R.id.av_video_layer_ui);//surfaceView;
        coverView=(RelativeLayout)findViewById(R.id.live_room_cover_view);
        coverImage=(FrescoImageView)findViewById(R.id.live_video_cover_image);
        coverImage.setImageURI(Uri.parse(CurLiveInfo.getHostAvator()));
        loadView=(ImageView)findViewById(R.id.loadingImageView);
        loadAniDraw = (AnimationDrawable)loadView.getBackground();
        loadAniDraw.start();
        countDownAnim= AnimationUtils.loadAnimation(this, R.anim.host_start_count_down);
        countDownAnim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                mHandler.sendEmptyMessage(HIDE_COUNT_DOWN_VIEW);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        countView=(TextView)findViewById(R.id.start_count_view);
        if(MySelfInfo.getInstance().getIdStatus()== Constants.HOST) {
            //主播开播放倒计时动画
            if (countView != null) {
                for (int i = count; i > 0; i--) {
                    Message msg = mHandler.obtainMessage();
                    msg.what = COUNT_DOWN_START;
                    msg.obj = i;
                    mHandler.sendMessageDelayed(msg, (count - i + 1) * 1000);
                }
            }
        }
    }

    /**
     * 初始化主播应答连麦请求对话框
     */
    private void initHostInteractDlg(){
        hostInteractDlg= new Dialog(this, R.style.dialog);
        hostInteractDlg.setCanceledOnTouchOutside(false);
        hostInteractDlg.setContentView(R.layout.host_interact_dialog);
        memberInteractInfo = (TextView) hostInteractDlg.findViewById(R.id.host_interact_dialog_description);
        memberInteractInfo.setText("");
        interactInfoFormat=getString(R.string.ui_video_interact_description);
        hostInteractDlg.findViewById(R.id.host_interact_dialog_agree).setOnClickListener(this);
        hostInteractDlg.findViewById(R.id.host_interact_dialog_refuse).setOnClickListener(this);
        Window dialogWindow = hostInteractDlg.getWindow();
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();
        dialogWindow.setGravity(Gravity.CENTER);
        dialogWindow.setAttributes(lp);
    }

    /**
     * 初始化闭麦请求对话框
     */
    private void initHostCancelInteractDlg(){
        hostCancelInteractDlg= new Dialog(this, R.style.dialog);
        hostCancelInteractDlg.setCanceledOnTouchOutside(true);
        hostCancelInteractDlg.setContentView(R.layout.host_cancel_interact_dialog);
        interactMemberHeadView=(FrescoImageView)hostCancelInteractDlg.findViewById(R.id.interact_member_head_view);
        interactMemberNick = (TextView) hostCancelInteractDlg.findViewById(R.id.interact_member_nick_view);
        interactMemberNick.setText("");
        hostCancelInteractDlg.findViewById(R.id.host_close_interact_video).setOnClickListener(this);
        hostCancelInteractDlg.findViewById(R.id.host_cancel_interact_dialog_close).setOnClickListener(this);
        Window dialogWindow = hostCancelInteractDlg.getWindow();
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();
        dialogWindow.setGravity(Gravity.CENTER);
        dialogWindow.setAttributes(lp);
    }

    /**
     * 初始化成员连麦状态对话框
     */
    private void initMultiVideoStateDlg(){
        waitHostResponseMsg=getString(R.string.ui_video_interact_wait);
        multiVideoStateDlg= new Dialog(this, R.style.dialog);
        multiVideoStateDlg.setCanceledOnTouchOutside(true);
        multiVideoStateDlg.setContentView(R.layout.member_multi_video_state_dialog);
        multiVideoStateView = (TextView) multiVideoStateDlg.findViewById(R.id.multi_video_state_dlg_title);
        multiVideoStateView.setText(waitHostResponseMsg);
        multiVideoStateDlg.findViewById(R.id.close_multi_video_state_dlg).setOnClickListener(this);
        Window dialogWindow = multiVideoStateDlg.getWindow();
        WindowManager.LayoutParams lp = dialogWindow.getAttributes();
        dialogWindow.setGravity(Gravity.CENTER);
        dialogWindow.setAttributes(lp);
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.multi_video_opera_btn:
                //某成员端实例向主播发起连麦请求
                onMemberRequestMultiVideo();
                break;
            case R.id.host_interact_dialog_agree://主播端实例同意连麦
                mHandler.removeMessages(TIMEOUT_RESPONSE);//不再做应答超时处理
                //向请求端实例发送C2C消息，回答为同意，发起请求的成员端实例改变成员角色，使其上麦
                if(DEBUG_INTERACT){
                    Toast.makeText(this,"同意连麦："+memberInteractInfo.getTag(),Toast.LENGTH_LONG).show();
                }
                if(memberInteractInfo.getTag()!=null){
                    mRoomPresenter.sendC2CMessage(Constants.AV_IM_CMD_MUlTI_MEMBER_REQ_JOIN_VIDEO_AGREE,"",memberInteractInfo.getTag().toString());
                }
                if(hostInteractDlg!=null&&hostInteractDlg.isShowing()){//隐藏连麦应答对话框
                    hostInteractDlg.dismiss();
                }
                break;
            case R.id.host_interact_dialog_refuse://主播端实例拒绝连麦
                mHandler.removeMessages(TIMEOUT_RESPONSE);//不再做应答超时处理
                if(memberInteractInfo.getTag()!=null){
                    String id=memberInteractInfo.getTag().toString();
                    if(id==null||"".equals(id)){
                        return;
                    }
                    delMember(id);
                    //向请求端实例发送C2C消息，回答为拒绝
                    refuseMultiVideo(id);
                }
                if(hostInteractDlg!=null&&hostInteractDlg.isShowing()){//隐藏连麦应答对话框
                    hostInteractDlg.dismiss();
                }
                if(memberVideoCount>0){//连麦个数减少一个
                    memberVideoCount--;//连麦个数-1
                }
                break;
            case R.id.host_close_interact_video://主播取消某个互动视频
                if(interactMemberNick.getTag()!=null) {
                    String memberId = interactMemberNick.getTag().toString();
                    cancelMemberView(memberId);
                }
            case R.id.host_cancel_interact_dialog_close:
                if(hostCancelInteractDlg!=null){
                    hostCancelInteractDlg.dismiss();
                }
                break;
            case R.id.close_multi_video_state_dlg:
                if(multiVideoStateDlg!=null){
                    multiVideoStateDlg.dismiss();
                }
                break;
            default:
                break;
        }
    }

    private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
                case TIMEOUT_RESPONSE:
                    if(hostInteractDlg!=null&&hostInteractDlg.isShowing()){
                        hostInteractDlg.dismiss();
                    }
                    if(msg.obj!=null){
                        String id=msg.obj.toString();
                        if(id==null||"".equals(id)){
                            break;
                        }
                        removeInteractMember(id);
                        refuseMultiVideo(id);
                    }
                    if(memberVideoCount>0){//连麦个数减少一个
                        memberVideoCount--;//连麦个数-1
                    }
                    break;
                case REFRESH_JOIN_REQ://成员端刷新连麦状态
                    if(win!=null){
                        win.interactiveVideoEnable(true);//成员端刷新连麦状态,显示连麦按钮
                    }
                    if(multiVideoStateDlg!=null&&multiVideoStateDlg.isShowing()){
                        multiVideoStateDlg.dismiss();
                    }
                    break;
                case COUNT_DOWN_START:
                    mHandler.removeMessages(HIDE_COUNT_DOWN_VIEW);
                    if(countView!=null){
                        if(countView.getVisibility()!=View.VISIBLE){
                            countView.setVisibility(View.VISIBLE);
                        }
                        countView.clearAnimation();
                        countView.setText(msg.obj.toString());
                        countView.startAnimation(countDownAnim);
                    }
                    break;
                case HIDE_COUNT_DOWN_VIEW:
                    if(countView.getVisibility()==View.VISIBLE){
                        countView.setVisibility(View.INVISIBLE);
                    }
                    break;
                case ADD_VIDEO_REQUEST:
                    if(msg.obj!=null&&msg.obj instanceof MsgSender){
                        MsgSender m=(MsgSender)msg.obj;
                        addInteractMember(m);
                    }
                    break;
                case SHOW_ROOM_PAY:
                    checkPayRoom(null);
                    break;
                case ROOM_PAY_EXCUTE:
                    requestPayRoom();
                    break;
                default:
                    break;
            }
            return false;
        }
    });

    /**
     * 向主播发起连麦申请，只有不是主播才能发起申请
     * 1.先向后台发送验证，是否有资格连麦,无资格，提示不可连麦，有资格转到2
     * 2.向主播发送私信，申请连麦，等待主播应答：a.主播同意转到,b.超时应答或主播拒绝
     */
    private void onMemberRequestMultiVideo(){
        boolean noCamera=false;
        Camera c=null;
        try{
            c=Camera.open();
        }catch (Exception e){
            noCamera=true;
        }finally {
            try {
                if (c != null) {
                    c.release();
                }
            }catch (Exception e){

            }
        }
        if(noCamera){
            Toast.makeText(this,getString(R.string.camera_disable_msg),Toast.LENGTH_LONG).show();
            return;
        }
        //检测音视频权限
        //显示邀请状态:正在请求连麦中...
        //发送单聊通知给主播，等待应答
        MsgModel msgModel=new MsgModel();
        msgModel.setUserAction(Constants.AV_IM_CMD_MUlTI_MEMBER_REQ_JOIN_VIDEO);
        MultiVideoMsg msg=new MultiVideoMsg();
        msg.setFuser(mMsgSender);
        msgModel.setActionParam(OKHttp.GSON.toJson(msg));
        mRoomPresenter.sendC2CMsg(OKHttp.GSON.toJson(msgModel), CurLiveInfo.hostID);
        if(win!=null){
            win.interactiveVideoEnable(false);//隐藏连麦按钮，防止多次请求
        }
        if(multiVideoStateDlg!=null){
            if(multiVideoStateView!=null){
                multiVideoStateView.setText(waitHostResponseMsg);
            }
            multiVideoStateDlg.show();
        }
        mHandler.sendEmptyMessageDelayed(REFRESH_JOIN_REQ,20*1000);////成员请求连麦，若超过20秒未收到任何应答，刷新连麦状态
    }

    /**
     * 主播显示连麦请求对话框视图
     */
    @Override
    public void onHostShowMultiVideoDialog(MsgSender msgSender){
        if(DEBUG_INTERACT){
            Toast.makeText(this,"我是主播，收到连麦请求后，当前我的连麦数:"+memberVideoCount+"@@@"+msgSender.getUid(),Toast.LENGTH_LONG).show();
        }
        if(memberVideoCount<3){
            memberVideoCount++;//连麦个数加1
        }else{
            //连麦个数已上限,系统直接回应拒绝
            refuseMultiVideo(msgSender.getUid());
            return;
        }
        Message message=mHandler.obtainMessage();
        message.what=ADD_VIDEO_REQUEST;
        message.obj= msgSender;
        mHandler.sendMessage(message);
        //interactMembers.add(sender);
        if(hostInteractDlg==null){
            initHostInteractDlg();
        }
        memberInteractInfo.setText(String.format(interactInfoFormat,msgSender.getNickname()));
        memberInteractInfo.setTag(msgSender.getUid());
        hostInteractDlg.show();
        //对话框显示超过20秒未做任何操作，做应答超时处理，实为拒绝了连麦请求
        Message msg = mHandler.obtainMessage();
        msg.what = TIMEOUT_RESPONSE;
        msg.obj = msgSender.getUid();
        mHandler.sendMessageDelayed(msg, 20 * 1000);
    }

    /**
     * 请求连麦的成员端实例收到主播应答
     * @param isSuccess true主播同意连麦,false连麦失败或被拒绝
     * @param msg 应答结果额外消息
     */
    @Override
    public void onHostResponseMultiVideo(boolean isSuccess,String msg){
        mHandler.removeMessages(REFRESH_JOIN_REQ);//不理处理超时刷新逻辑
        if(isSuccess){
            if(multiVideoStateDlg!=null&&multiVideoStateDlg.isShowing()){//隐藏等待应答对话框
                multiVideoStateDlg.dismiss();
            }
            //变为视频互动成员，角色更改成功后，线路自动切换到中心机房，上传成员端视频数据
            if(DEBUG_INTERACT) {
                Toast.makeText(this, "我是请求者，主播同意和我连麦!", Toast.LENGTH_LONG).show();
            }
            mRoomPresenter.changeRole(Constants.VIDEO_MEMBER_ROLE,true);
            if(DEBUG_INTERACT) {
                Toast.makeText(this, "变更角色上麦成功!", Toast.LENGTH_LONG).show();
            }
            //原流程为发送一条私聊消息给主播，告知连麦成功，此处仍然发送但不处理
        }else{//连麦失败或被拒绝
            if(MySelfInfo.getInstance().getIdStatus()!= Constants.HOST) {
                if (win != null) {//显示连麦按钮
                    win.interactiveVideoEnable(true);
                }
                if(multiVideoStateView!=null){
                    multiVideoStateView.setText(msg);
                }
                if(multiVideoStateDlg!=null&&!isFinishing()){
                    multiVideoStateDlg.show();
                }
            }
            Toast.makeText(this,msg,Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 拒绝连麦
     * @param uid 被拒绝的uid
     */
    private void refuseMultiVideo(String uid){
        mRoomPresenter.sendC2CMessage(Constants.AV_IM_CMD_MUlTI_MEMBER_REQ_JOIN_VIDEO_REFUSE,"",uid);//发送c2c消息，拒绝
    }

    /**
     * 成员被迫下麦，主播发出闭麦命令
     */
    @Override
    public void onCancelMemberInteractVideo() {
        if(MySelfInfo.getInstance().getLvl()>= Constants.INTERACT_MIN_LVL){
            if(win!=null){
                win.interactiveVideoEnable(true);
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        QavsdkControl.getInstance().getAVContext().getAudioCtrl().enableSpeaker(true);
        QavsdkControl.getInstance().onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        QavsdkControl.getInstance().getAVContext().getAudioCtrl().enableSpeaker(false);
        QavsdkControl.getInstance().onPause();
    }

    /**
     * 启动心跳
     */
    private void startHeartBeat(){
        if(heartParam==null){
           heartParam= OKHttpParam.builder(false);
        }
        if(heartBeatTimer==null){
            heartBeatTimer=new Timer(true);
        }
        if(heartBeatTask==null){
            heartBeatTask=new HeartBeatTask();
        }
        heartBeatTimer.schedule(heartBeatTask,0,30*1000);
    }

    /**
     * 主播初始化在线人数,只需初始化一次
     * @param online
     */
    public void onHostInitOnlineCount(long online){
        if(isInitReportOnlineCount){
            return;
        }
        isInitReportOnlineCount=true;
        watchCount.set(online);
        mOnlineCount.set(online);
        mHandler.post(new HeartBeatTask());
    }
    /**
     * 心跳任务
     */
    private class HeartBeatTask extends TimerTask {
        @Override
        public void run() {
            heartParam.put("uid", CurLiveInfo.getHostID());
            heartParam.put("watchCount",watchCount.get());
            heartParam.put("onlineCount",mOnlineCount.get()+"");
            heartParam.put("admireCount", CurLiveInfo.getAdmires());
            long time=System.currentTimeMillis()-liveStartTime;
            if(time>1000){
                time=time/1000;
            }else{
                time=0;
            }
            heartParam.put("timeSpan",time);
            OKHttp.post(HttpConfig.KKY_HEART_BEAT, heartParam.jsonParam(), TAG, heartHandler);
        }
    }

    /**
     * 心跳处理
     */
    private OKHttpUIHandler heartHandler=new OKHttpUIHandler(OKHttpResponseModel.class) {
        @Override
        public void onSuccess(Object model) {
            KKYUtil.log("心跳成功！");
        }

        @Override
        public void onErr(String errMsg) {
            KKYUtil.log("心跳异常:" + errMsg);
        }
    };

    /**
     * 点击Back键
     */
    @Override
    public void onBackPressed() {
        if(MySelfInfo.getInstance().getIdStatus()!= Constants.HOST) {//成员主动退出
            if (QavsdkControl.getInstance().containIdView(MySelfInfo.getInstance().getId())) {//处于互动视频中
                cancelMemberView(MySelfInfo.getInstance().getId());//取消互动
            }
        }
        quiteLiveByPurpose();
    }

    /**
     * 主动退出直播
     */
    private void quiteLiveByPurpose() {
        if (MySelfInfo.getInstance().getIdStatus() == Constants.HOST) {
            KKYUtil.log("主播主动结束直播...");
            interactiveDialog(getString(R.string.ui_host_finish_title), getString(R.string.ui_host_finish_desc), new OnDialogClickListener() {
                @Override
                public void onOk() {
                    //如果是直播，发消息
                    if(CurLiveInfo.isIsRecording()){//正在录制视频，则先停止录制，再执行退出房间流程
                        CurLiveInfo.setIsRecording(false);
                        mRoomPresenter.stopRecord(new TIMValueCallBack<List<String>>(){
                            @Override
                            public void onError(int i, String s) {
                                KKYUtil.log("停止录制错误：" + i + " msg:" + s);
                                Toast.makeText(RoomVideoRoom.this,getString(R.string.live_record_failed),Toast.LENGTH_LONG).show();
                                if(KKYUtil.DEBUG) {
                                    Toast.makeText(RoomVideoRoom.this,"call quiteLiveByPurpose stop recording err!", Toast.LENGTH_LONG).show();
                                }
                                if (null != mRoomPresenter) {
                                    mRoomPresenter.prepareQuitRoom(true);
                                }
                            }

                            @Override
                            public void onSuccess(List<String> strings) {
                                recordIds=strings.toArray(new String[1]);
                                if(KKYUtil.DEBUG) {
                                    Toast.makeText(RoomVideoRoom.this, "call quiteLiveByPurpose stop recording Success!", Toast.LENGTH_LONG).show();
                                }
                                if (null != mRoomPresenter) {
                                    mRoomPresenter.prepareQuitRoom(true);
                                }
                                String names="";
                                for (String ids:strings){
                                    names+=ids;
                                }
                                KKYUtil.log("已停止录制：" + names);
                            }
                        });
                    }else{
                        if(KKYUtil.DEBUG){
                            Toast.makeText(RoomVideoRoom.this,"call quiteLiveByPurpose not recording!",Toast.LENGTH_LONG).show();
                        }
                        if (null != mRoomPresenter) {
                            mRoomPresenter.prepareQuitRoom(true);
                        }
                    }
                }

                @Override
                public void onCancel() {
                }
            });
        } else {
            KKYUtil.log("成员主动结束直播...");
            mRoomPresenter.prepareQuitRoom(true);
        }
    }

    /**
     * 加入房间时直播已结束
     */
    @Override
    public void onEndEnter() {
        if(win!=null){
            win.dismiss();
        }
        if(liveExtraView!=null){
            liveExtraView.setVisibility(View.INVISIBLE);
        }
        if(loadView!=null){
            loadView.setVisibility(View.INVISIBLE);
        }
        showLiveResult(true);
    }

    /**
     * 被动退出直播
     */
    private void quiteLivePassively() {
        if(MySelfInfo.getInstance().getIdStatus()== Constants.HOST) {
            KKYUtil.log("主播被动退出房间");
        }else{
            KKYUtil.log("成员被动退出房间");
        }
        mRoomPresenter.prepareQuitRoom(false);
    }

    @Override
    public void readyToQuit() {
        mEnterRoomHelper.quiteLive();
    }

    /**
     * 完成进出房间流程,进入房间
     *
     * @param id_status
     * @param isSucc
     */
    @Override
    public void enterRoomComplete(int id_status, boolean isSucc) {
        //必须得进入房间之后才能初始化UI
        mEnterRoomHelper.initAvUILayer(avView);
        //设置预览回调，修正摄像头镜像
        mRoomPresenter.setCameraPreviewChangeCallback();
        if (isSucc == true) {
            mRoomPresenter.pushStream();//开始推流
            //IM初始化
            mRoomPresenter.initTIMListener("" + CurLiveInfo.getRoomNum());
            if (id_status == Constants.HOST) {//主播方式加入房间成功
                //开启摄像头渲染画面
                liveStartTime=System.currentTimeMillis();//直播起始时间
            } else {
                //发消息通知上线
                enterMsg=new EnterMsg();
                mMsgSender.setLvl(MySelfInfo.getInstance().getLvl());
                enterMsg.setFuser(mMsgSender);
                if(msgModel==null){
                    msgModel=new MsgModel();
                }
                msgModel.setUserAction(Constants.AVIMCMD_EnterLive);
                msgModel.setActionParam(gson.toJson(enterMsg));
                mRoomPresenter.sendGroupNoticeMsg(gson.toJson(msgModel), new TIMValueCallBack<TIMMessage>() {
                    @Override
                    public void onError(int i, String s) {

                    }

                    @Override
                    public void onSuccess(TIMMessage message) {
                        memberJoin(enterMsg);
                    }
                });
            }
            //主播通知后台服务器
            //不是主播，直接请求房间数据
            if(MySelfInfo.getInstance().getIdStatus()!= Constants.HOST){
                startSuccess();
            }
        }else{
            if(KKYUtil.DEBUG){
                Toast.makeText(this,"加入房间失败：",Toast.LENGTH_LONG).show();
            }
        }
    }

    /**
     * 成功退出直播
     * @param id_status
     * @param succ
     */
    @Override
    public void quiteRoomComplete(int id_status, boolean succ) {
        if(win!=null){
            win.dismiss();
        }
        if(isForceLoginOut){//强制下线
            Intent forceLoginOut=new Intent(this, ForceLoginOut.class);
            forceLoginOut.putExtra(ForceLoginOut.REASON_MSG, getString(R.string.login_force_out));
            startActivity(forceLoginOut);
        }
        if (MySelfInfo.getInstance().getIdStatus() == Constants.HOST) {//主播退出
            OKHttpParam param= OKHttpParam.builder();
            param.put("uid", MySelfInfo.getInstance().getId());
            param.put("watchCount",watchCount.get());
            param.put("admireCount", CurLiveInfo.getAdmires());
            param.put("onlineCount",mOnlineCount.get()+"");
            liveTotalTime=System.currentTimeMillis()-liveStartTime;
            param.put("timeSpan",liveTotalTime/1000);
            if(recordIds!=null&&recordIds.length!=0){
                param.put("videoID",recordIds);
            }
            OKHttp.post(HttpConfig.API_LIVE_END, param.jsonParam(), TAG, new OKHttpUIHandler(OKHttpResponseModel.class) {
                @Override
                public void onSuccess(Object model) {
                    KKYUtil.log(TAG, "请求退出房间成功!");
                    if (heartBeatTimer != null) {
                        heartBeatTimer.cancel();
                        heartBeatTimer = null;
                    }
                    if (heartBeatTask != null) {
                        heartBeatTask.cancel();
                        heartBeatTask = null;
                    }
                    if(isForceLoginOut){
                        finish();
                        return;
                    }
                    showLiveResult(false);
                }

                @Override
                public void onErr(String errMsg) {
                    if (heartBeatTimer != null) {
                        heartBeatTimer.cancel();
                        heartBeatTimer = null;
                    }
                    if (heartBeatTask != null) {
                        heartBeatTask.cancel();
                        heartBeatTask = null;
                    }
                    if(isForceLoginOut){
                        finish();
                        return;
                    }
                    showLiveResult(false);
                }
            });
        } else {//成员退出
            if(isForceLoginOut){
                finish();
                return;
            }
            if(isShowResult){
                showLiveResult(false);
                return;
            }
            finish();
        }
    }

    /**
     * 显示直播结果
     */
    public void showLiveResult(boolean inAVRoom){
        //直播结束，显示直播结果
        if(isFinishing()||resultDialog==null){
            return;
        }
        OKHttpParam httpParam= OKHttpParam.builder(false);
        httpParam.put("uid", CurLiveInfo.getHostID());
        OKHttp.post(HttpConfig.API_LIVE_END_INFO, httpParam.jsonParam(), TAG, new OKHttpUIHandler(LiveEndModel.class) {
            @Override
            public void onSuccess(Object model) {
                LiveEndModel m = (LiveEndModel) model;
                KKYUtil.log("直播结束结果数据：" + m.getResponseStr());
                if (resultDialog != null) {
                    resultDialog.setWatchCountView(m.getData().getVatch());
                    if (MySelfInfo.getInstance().getIdStatus() == Constants.HOST) {
                        resultDialog.setTicketsView(m.getData().getVote());
                        resultDialog.setPraiseView(m.getData().getAdmire());
                    }
                    if (m.getData() != null && "1".equals(m.getData().getType())) {//私密直播，隐藏分享栏
                        KKYUtil.log("当前直播为私密直播");
                        resultDialog.hideShareBar();
                    }
                    try {
                        String h = getString(R.string.ui_duration_hour);
                        String minute = getString(R.string.ui_duration_minute);
                        String s = getString(R.string.ui_duration_second);
                        String duration = m.getData().getTime();
                        KKYUtil.log("直播时长" + duration + "秒");
                        String time = KKYUtil.dateFormatHMS(Long.parseLong(duration) * 1000, h, minute, s);
                        resultDialog.setDurationView(time);
                    } catch (Exception e) {

                    }

                }
            }

            @Override
            public void onErr(String errMsg) {

            }
        });
        if(MySelfInfo.getInstance().getIdStatus()== Constants.HOST) {
            resultDialog.showHost(true);
        }else{
            resultDialog.showHost(false);
        }
        resultDialog.setInAVRoom(inAVRoom);
        resultDialog.show();
    }

    /**
     * 直播结果窗口关闭
     * @param inAVRoom
     */
    public void onLiveResultClose(boolean inAVRoom) {
        if(inAVRoom){
            mEnterRoomHelper.quiteLive();
        }else {
            finish();
        }
    }

    /**
     * 观看人数纠正(观看人数不会小于在线人数)
     */
    public void syncWatchCount(long online){
        long current=watchCount.get();
        if(current<online){
            watchCount.set(online);
        }
    }

    /**
     * 成员状态变更，有用户加入房间，
     * 1.做观看人数累加
     * 2.刷新在线列表
     *
     */
    @Override
    public void memberJoin(EnterMsg enterMsg) {
        KKYUtil.log(enterMsg.getFuser().getNickname() + "进入房间");
        watchCount.incrementAndGet();
        mOnlineCount.incrementAndGet();
        CurLiveInfo.setMembers(watchCount.get());
        if(win!=null){
            win.onMemberJoin(enterMsg);
        }
    }

    /**
     * 有用户离开房间
     * 1.做观看人数减去
     * 2.刷新在线列表
     * @param id
     * @param name
     */
    @Override
    public void memberQuit(String id, String name) {
        KKYUtil.log(name + "离开房间");
        mOnlineCount.decrementAndGet();
        if (CurLiveInfo.getMembers() > 1) {
            CurLiveInfo.setMembers(CurLiveInfo.getMembers() - 1);
        }
        if(interactMembers.containsKey(id)){//防止成员端点击麦请求后，主播还未来得应答成员就直接退出房间
            interactMembers.remove(id);
            if(memberVideoCount>0){
                memberVideoCount--;
            }
        }
        if(win!=null){
            win.onMemberExit(id);
        }
        //如果存在视频互动，取消
        QavsdkControl.getInstance().closeMemberView(id);
    }


    /**
     * 有成员退群,大于50人时，不能再用此方法
     *
     * @param list 成员ID 列表
     */
    @Override
    public void memberQuiteLive(String[] list) {
        if (list == null) return;
        for (String id : list) {
            if (CurLiveInfo.getHostID().equals(id)) {
                if (MySelfInfo.getInstance().getIdStatus() == Constants.MEMBER) {
                    isShowResult=true;
                    quiteLivePassively();
                }
            }
        }
    }


    /**
     * 有成员入群
     *
     * @param list 成员ID 列表
     */
    @Override
    public void memberJoinLive(final String[] list) {
        //TODO NOTHING
    }

    @Override
    public void alreadyInLive(String[] list) {
        for (String id : list) {
            if (id.equals(MySelfInfo.getInstance().getId())) {
                QavsdkControl.getInstance().setSelfId(MySelfInfo.getInstance().getId());
                QavsdkControl.getInstance().setLocalHasVideo(true, MySelfInfo.getInstance().getId());
            } else {
                QavsdkControl.getInstance().setRemoteHasVideo(true, id, AVView.VIDEO_SRC_TYPE_CAMERA);
            }
        }

    }

    /**
     * 加载视频数据
     * @param isLocal 是否是本地数据
     * @param id      身份
     */
    @Override
    public void showVideoView(boolean isLocal, String id) {
        //渲染本地Camera
        if (isLocal == true) {
            QavsdkControl.getInstance().setSelfId(MySelfInfo.getInstance().getId());
            QavsdkControl.getInstance().setLocalHasVideo(true, MySelfInfo.getInstance().getId());
            //主播通知用户服务器
            if (MySelfInfo.getInstance().getIdStatus() == Constants.HOST) {
                //mEnterRoomHelper.notifyServerCreateRoom();
            }
        } else {
            QavsdkControl.getInstance().setRemoteHasVideo(true, id, AVView.VIDEO_SRC_TYPE_CAMERA);
        }

    }

    /**
     * 显示连麦申请对话框，同意或拒绝
     */
    @Override
    public void showInviteDialog() {
        //TODO NOTHING
    }

    @Override
    public void hideInviteDialog() {
        //TODO NOTHING

    }

    /**
     * 刷新聊天列表 name:text
     * @param text
     * @param name
     */
    @Override
    public void refreshText(String text, String name) {
        //TODO NOTHING
    }

    /**
     * 播放点赞动画，并累加点赞数
     */
    @Override
    public void refreshThumbUp() {
        CurLiveInfo.setAdmires(CurLiveInfo.getAdmires() + 1);
    }

    /**
     * 刷新直播界面
     * @param id
     */
    @Override
    public void refreshUI(String id) {

    }

    /**
     *
     * 检测并发送连麦邀请
     * 1.检查连麦上限数
     * @param id
     * @return
     */
    @Override
    public boolean showInviteView(String id) {
        //TODO NOTHING
       return false;
    }

    /**
     * 取消连麦请求
     * @param id
     */
    @Override
    public void cancelInviteView(String id) {
        //删除请求的id
        //TODO NOTHING
    }

    /**
     * 取消连麦，连麦时断开视频
     * @param id
     */
    @Override
    public void cancelMemberView(String id) {
        mRoomPresenter.sendGroupMessage(Constants.AVIMCMD_MULTI_CANCEL_INTERACT, id);//发下麦通知
        if (MySelfInfo.getInstance().getIdStatus() == Constants.HOST) {
            if(DEBUG_INTERACT) {
                Toast.makeText(this, "我是主播，发下麦广播通知" + id + "下麦", Toast.LENGTH_LONG).show();
            }
            if(memberVideoCount>0){
                memberVideoCount--;
            }
            delMember(id);

        } else {
            if(DEBUG_INTERACT) {
                Toast.makeText(this, "通知所有人我下麦", Toast.LENGTH_LONG).show();
            }
            mRoomPresenter.changeRole(Constants.NORMAL_MEMBER_ROLE,false);//更换角色
            if(DEBUG_INTERACT) {
                Toast.makeText(this, "我的角色变更为普通成员", Toast.LENGTH_LONG).show();
            }
        }
        QavsdkControl.getInstance().closeMemberView(id);
        if(DEBUG_INTERACT) {
            Toast.makeText(this, "A关闭小视频：" + id, Toast.LENGTH_LONG).show();
        }
        backToNormalCtrlView();
    }

    /**
     * 刷新连麦个数
     */
    @Override
    public void hostUpdateVideoCount(String id){
        if(memberVideoCount>0){
            memberVideoCount--;
        }
        delMember(id);
        if(DEBUG_INTERACT) {
            Toast.makeText(this, "我是主播，有人下麦后，当前我的连麦数:" + memberVideoCount, Toast.LENGTH_LONG).show();
        }
    }

    /**
     * 删除连麦者
     * @param id
     */
    private void delMember(String id){
        Message message=mHandler.obtainMessage();
        message.what=DEL_VIDEO_REQUEST;
        message.obj=id;
        mHandler.sendMessage(message);
    }

    /**
     * 移除互动组成员
     * @param id
     */
    private void removeInteractMember(String id){
        synchronized (interactMembers){
            interactMembers.remove(id);
        }
    }

    /**
     * 添加请求成员
     * @param msgSender
     */
    private void addInteractMember(MsgSender msgSender){
        synchronized (interactMembers){
            interactMembers.put(msgSender.getUid(), msgSender);
        }
    }

    /**
     * 获得某个已请求的成员
     * @param id
     * @return
     */
    private MsgSender getInteractMember(String id){
        synchronized (interactMembers){
            return interactMembers.get(id);
        }
    }

    /**
     * 统计已请求的成员个数
     * @return
     */
    private int countInteractMembers(){
        synchronized (interactMembers){
            return interactMembers.size();
        }
    }

    /**
     * 退出连麦，消息通知执行
     * @param id
     */
    public void memberQuiteVideo(String id) {
        //自己，刷新
        if(MySelfInfo.getInstance().getId().equals(id)) {
            if(win!=null){
                win.interactiveVideoEnable(true);
            }
        }
        //主播端
        if(MySelfInfo.getInstance().getIdStatus()== Constants.HOST){
            if(memberVideoCount>0){
                memberVideoCount--;
            }
        }
    }

    /**
     * 返回正常UI控制界面
     */
    private void backToNormalCtrlView() {
        //backGroundId = CurLiveInfo.getHostID(); TODO NOTHING
    }

    /**
     *
     * 推流成功
     * @param streamRes
     */
    @Override
    public void pushStreamSucc(TIMAvManager.StreamRes streamRes) {
        //TODO NOTHING
        List<TIMAvManager.LiveUrl> liveUrls = streamRes.getUrls();
        int length = liveUrls.size();
        String[] urls=new String[length];
        if(length>0){
            for (int i=0;i<length;i++){
                TIMAvManager.LiveUrl avUrl = liveUrls.get(i);
                String url = avUrl.getUrl();
                urls[i]=url;
                KKYUtil.log("推流地址：" + url);
            }
        }else{
            KKYUtil.log("推流地址为空");
        }
        //主播上报开播数据
        if (MySelfInfo.getInstance().getIdStatus() == Constants.HOST) {
            if(KKYUtil.DEBUG){
                Toast.makeText(this,"host pushStreamSuccess!",Toast.LENGTH_LONG).show();
            }
            mEnterRoomHelper.setStreamUrls(urls);
            mEnterRoomHelper.notifyServerCreateRoom();
        }
    }

    @Override
    public void pushStreamFailed(String msg) {
        if (null != mRoomPresenter) {
            if(KKYUtil.DEBUG){
                Toast.makeText(this,"pushStreamFailed:"+msg,Toast.LENGTH_LONG).show();
            }
            mRoomPresenter.prepareQuitRoom(true);
        }
    }

    /**
     * 获取房间信息，显示房间界面对话框
     */
    @Override
    public void startSuccess() {
        if(MySelfInfo.getInstance().getIdStatus()== Constants.HOST) {
            startHeartBeat();//是主播开始心跳
        }
        OKHttpParam param= OKHttpParam.builder();
        param.put("uid", CurLiveInfo.getHostID());
        OKHttp.post(HttpConfig.API_GET_LIVE_INFO, param.jsonParam(), TAG, new OKHttpUIHandler(LiveRoomMode.class) {
            @Override
            public void onSuccess(Object model) {
                LiveRoomMode m = (LiveRoomMode) model;
                KKYUtil.log("请求房间数据：" + m.getResponseStr());
                LiveRoomInfo roomInfo = m.getData();
                roomLiveNo = roomInfo.getLiveid();
                liveExtraView.setText("ID "+ CurLiveInfo.getHostID());
                if (win == null) {
                    win = new LiveRoomWin(RoomVideoRoom.this, roomInfo);
                    EventBus.getDefault().register(win);
                }
                win.setOwnerActivity(RoomVideoRoom.this);
                win.getWindow().getAttributes().width = (int) KKYApp.getInstance().screenWidth;
                if (!isFinishing()) {
                    //判断是否能录制视频，如等级大于多少才能录制
                    if (MySelfInfo.getInstance().getIdStatus() == Constants.HOST) {
                        mRoomPresenter.roomRecord(roomLiveNo);//主播开始录制视频
                    }
                    win.show();
                    if (MySelfInfo.getInstance().getIdStatus() != Constants.HOST) {//不是主播
                        if(roomInfo.getCharge()!=null){//收费房间
                            rate=roomInfo.getCharge().getPrice();
                            if (rate > 0) {//费率大于0请求扣费
                                if (KKYUtil.DEBUG) {
                                    Toast.makeText(RoomVideoRoom.this, "this is a Pay room " + roomInfo.getCharge().getFree(), Toast.LENGTH_LONG).show();
                                }
                                long freeTime=roomInfo.getCharge().getFree();
                                mHandler.sendEmptyMessageDelayed(SHOW_ROOM_PAY, freeTime*1000);//显示扣费提示
                            } else {
                                if (KKYUtil.DEBUG) {
                                    Toast.makeText(RoomVideoRoom.this, "this is a free room", Toast.LENGTH_LONG).show();
                                }
                            }
                        }
                    }
                }
            }

            @Override
            public void onErr(String errMsg) {
                KKYUtil.log(errMsg);
                if (KKYUtil.DEBUG) {
                    Toast.makeText(RoomVideoRoom.this, "Create Room Success,but Request live Info Err!" + errMsg, Toast.LENGTH_LONG).show();
                }
                if (null != mRoomPresenter) {
                    mRoomPresenter.prepareQuitRoom(true);
                }
            }
        });
    }


    /**
     * 检测房间扣费
     */
    final private void checkPayRoom(String msg){
        if(isFinishing()){
            return;
        }
        if(rate==0){
            return;
        }
        long balance=MySelfInfo.getInstance().getMoney();
        if(payDialog==null){
            payDialog=new RoomCoverDialog(this,rate);
            payDialog.setOnRoomPayListener(this);
            payDialog.getWindow().getAttributes().width=(int)KKYApp.getInstance().screenWidth;
        }
        if(balance>rate){
            //余额足够扣费
            payDialog.show(false);
        }else{
            //去充值
            payDialog.show(true);
        }
        payDialog.enablePay(true);
    }

    @Override
    public void onRoomPayCancel() {
        onBackPressed();
    }

    @Override
    public void onRoomPay(boolean isRecharge) {
        if(isRecharge){
            Intent recharge=new Intent(this,UserAccount.class);
            recharge.putExtra(UserAccount.ROOM_PAY_RECHARGE_ACTION,UserAccount.ROOM_PAY_RECHARGE_ACTION);
            startActivityForResult(recharge,REQUEST_PAY_RECHARGE);
        }else{
            requestPayRoom();
        }
    }

    /**
     * 向后台提交扣费请求
     */
    private void requestPayRoom(){
        if(payDialog!=null){
            payDialog.enablePay(false);
        }
        OKHttpParam param= OKHttpParam.builder(false);
        param.put("liveid",roomLiveNo);
        param.put("uid", CurLiveInfo.getHostID());
        OKHttp.post(HttpConfig.API_PAY_ROOM_BY_PERIOD, param.jsonParam(), TAG, new OKHttpUIHandler(RoomPayModel.class) {
            @Override
            public void onSuccess(Object model) {
                mHandler.removeMessages(SHOW_ROOM_PAY);
                mHandler.removeMessages(ROOM_PAY_EXCUTE);
                RoomPayModel m = (RoomPayModel) model;
                EventBus.getDefault().post(new OnUpdateBalance(MySelfInfo.getInstance().updateMoney(RoomVideoRoom.this,false,rate)));//更新余额
                MySelfInfo.getInstance().updateCacheInt(RoomVideoRoom.this, Constants.USER_LVL, m.getData().getLvl());
                if(isFinishing()){
                    return;
                }
                if(payDialog!=null&&payDialog.isShowing()){
                    payDialog.dismiss();
                    payDialog.enablePay(true);
                }
                mHandler.sendEmptyMessageDelayed(ROOM_PAY_EXCUTE,PAY_PERIOD);
                //判断等级，刷新连麦UI状态
                if (KKYUtil.DEBUG) {
                    Toast.makeText(RoomVideoRoom.this, "Pay Success!", Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onErr(String errMsg) {
                Toast.makeText(RoomVideoRoom.this, getString(R.string.ui_pay_failed), Toast.LENGTH_LONG).show();
                checkPayRoom(errMsg);//继续检测
            }
        });
    }

    /**
     * 收到IM消息
     */
    @Override
    public void onReceiveMsg(TIMMessage currMsg) {
        if(Constants.SERVER_ADMIN_ID.equals(currMsg.getConversation().getPeer())){
            return;
        }
        for (int j = 0; j < currMsg.getElementCount(); j++) {
            if (currMsg.getElement(j) == null) {
                continue;
            }
            TIMElem elem = currMsg.getElement(j);
            TIMElemType type = elem.getType();
            //系统消息(群已解散)
            if (type == TIMElemType.GroupSystem) {
                if (TIMGroupSystemElemType.TIM_GROUP_SYSTEM_DELETE_GROUP_TYPE == ((TIMGroupSystemElem) elem).getSubtype()) {
                    /**
                    sendBroadcast(new Intent(
                            Constants.ACTION_HOST_LEAVE));**/
                }
            }
            //定制消息
            if (type == TIMElemType.Custom) {
                if(win!=null&&win.isShowing()){
                    win.onReceiveCustomMsg(currMsg,elem);
                }
                continue;
            }
            //其他群消息过滤
            if (currMsg.getConversation() != null && currMsg.getConversation().getPeer() != null)
                if (!CurLiveInfo.getChatRoomId().equals(currMsg.getConversation().getPeer())) {
                    continue;
                }
            //最后处理文本消息
            if (type == TIMElemType.Text) {
                if(win!=null&&win.isShowing()){
                    win.onReceiveTxtMsg(currMsg,(TIMTextElem)elem);
                }
            }
        }
    }

    /**
     * 显示私信会话列表界面
     */
    public void showC2CListWin(){
       Intent c2cList=new Intent(this, C2CConversationManager.class);
       startActivity(c2cList);
    }

    @Override
    public void finish(){
        if(CurLiveInfo.isIsRecording()){
            CurLiveInfo.setIsRecording(false);
        }
        if(roomShareContent!=null){
            roomShareContent.release();
        }
        mHandler.removeCallbacksAndMessages(null);
        if(payDialog!=null&&payDialog.isShowing()){
            payDialog.dismiss();
        }
        super.finish();
    }

    /**
     * 广播处理器
     */
    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            //AvSurfaceView 初始化成功
            if (action.equals(Constants.ACTION_SURFACE_CREATED)) {
                //打开摄像头
                if (MySelfInfo.getInstance().getIdStatus() == Constants.HOST) {
                    mRoomPresenter.openCameraAndMic();
                }
            }
            //连麦或开播
            if (action.equals(Constants.ACTION_CAMERA_OPEN_IN_LIVE)) {//有人打开摄像头
                ArrayList<String> ids = intent.getStringArrayListExtra("ids");
                //如果是自己本地直接渲染
                for (String id : ids) {
                    if (id.equals(MySelfInfo.getInstance().getId())) {
                        showVideoView(true,id);
                        return;
                    }
                }
                //其他人一并获取
                int requestCount = CurLiveInfo.getCurrentRequestCount();
                mRoomPresenter.requestViewList(ids);
                requestCount = requestCount + ids.size();
                CurLiveInfo.setCurrentRequestCount(requestCount);
            }

            if (action.equals(Constants.ACTION_SWITCH_VIDEO)) {//点击成员回调,禁用切换
                //视频界面切换事件
                String uid=intent.getStringExtra(Constants.EXTRA_IDENTIFIER);
                if(MySelfInfo.getInstance().getIdStatus()== Constants.HOST){//主播
                    //Toast.makeText(LiveVideoRoom.this,"点击了视频ID:"+uid,Toast.LENGTH_LONG).show();
                    MsgSender member=getInteractMember(uid);
                    if(member!=null){//显示关闭连麦互动对话框
                        if(hostCancelInteractDlg==null){
                            initHostCancelInteractDlg();
                        }
                        interactMemberHeadView.setImageURI(Uri.parse(member.getAvatar()));
                        interactMemberNick.setText(member.getNickname());
                        interactMemberNick.setTag(uid);
                        hostCancelInteractDlg.show();
                    }else{
                        if(DEBUG_INTERACT) {
                            Toast.makeText(RoomVideoRoom.this, "本地未找到互动者成员：" + uid, Toast.LENGTH_LONG).show();
                        }
                    }
                }

            }

            if (action.equals(Constants.ACTION_HOST_LEAVE)) {//主播结束
                isShowResult=true;
                quiteLivePassively();
            }

        }
    };

    private void registerReceiver() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Constants.ACTION_SURFACE_CREATED);
        intentFilter.addAction(Constants.ACTION_HOST_ENTER);
        intentFilter.addAction(Constants.ACTION_CAMERA_OPEN_IN_LIVE);
        intentFilter.addAction(Constants.ACTION_SWITCH_VIDEO);
        intentFilter.addAction(Constants.ACTION_HOST_LEAVE);
        intentFilter.addAction(Constants.BD_EXIT_APP);
        registerReceiver(mBroadcastReceiver, intentFilter);
    }

    private void unregisterReceiver() {
        unregisterReceiver(mBroadcastReceiver);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if(requestCode==REQUEST_PAY_RECHARGE){
            if(RESULT_OK==resultCode){//充值界面返回
                if(KKYUtil.DEBUG){
                    Toast.makeText(this,"Recharge OK Back,call requestPayRoom...!",Toast.LENGTH_LONG).show();
                }
                requestPayRoom();//请求扣费
            }
            return;
        }
        super.onActivityResult(requestCode,resultCode,data);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,@NonNull int[] grantResults){
        if(requestCode==REQUEST_CODE_ASK_PERMISSIONS){
            for (int i=0;i<grantResults.length;i++) {
                if (grantResults[i] == PackageManager.PERMISSION_DENIED) {
                    switch (permissions[i]) {
                        case Manifest.permission.CAMERA:
                        case Manifest.permission.RECORD_AUDIO:
                            Toast.makeText(this,getString(R.string.av_disable_msg),Toast.LENGTH_LONG).show();
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    }


    @Override
    protected void onDestroy() {
        mRoomPresenter.stopPushAction();//停止推流
        if(CurLiveInfo.isIsRecording()){
            CurLiveInfo.setIsRecording(false);
        }
        if(roomShareContent!=null){
            roomShareContent.release();
        }
        try {
            CurLiveInfo.isInRoom=false;
            EventBus.getDefault().unregister(this);
            if(win!=null){
                EventBus.getDefault().unregister(win);
            }
            if(heartBeatTimer!=null){
                heartBeatTimer.cancel();
                heartBeatTimer=null;
            }
            if(heartBeatTask!=null){
                heartBeatTask.cancel();
                heartBeatTask=null;
            }
            mHandler.removeCallbacksAndMessages(null);
            super.onDestroy();
            Thread.currentThread().setUncaughtExceptionHandler(null);
            memberVideoCount = 0;
            CurLiveInfo.setMembers(0);
            CurLiveInfo.setAdmires(0);
            CurLiveInfo.setCurrentRequestCount(0);
            unregisterReceiver();
            QavsdkControl.getInstance().clearVideoMembers();
            QavsdkControl.getInstance().onDestroy();
            mRoomPresenter.onDestory();
            mEnterRoomHelper.onDestory();
            watchCount=null;
        }catch (NullPointerException e){
            e.printStackTrace();
        }
    }

    public class CustomExceptionHandler implements Thread.UncaughtExceptionHandler {
        private static final String TAG = "CustomExceptionHandler";
        private Thread.UncaughtExceptionHandler mDefaultUEH;
        public CustomExceptionHandler() {
            mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
        }

        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            CurLiveInfo.isInRoom=false;
            if(CurLiveInfo.isIsRecording()){
                CurLiveInfo.setIsRecording(false);
            }
            Log.e(TAG, "------------ CustomExceptionHandler ------------");
            CrashReport.postCatchedException(ex);
            if(heartBeatTimer!=null){
                heartBeatTimer.cancel();
                heartBeatTimer=null;
            }
            if(heartBeatTask!=null){
                heartBeatTask.cancel();
                heartBeatTask=null;
            }
            quiteLivePassively();
            Thread.currentThread().setUncaughtExceptionHandler(null);
            memberVideoCount = 0;
            CurLiveInfo.setMembers(0);
            CurLiveInfo.setAdmires(0);
            CurLiveInfo.setCurrentRequestCount(0);
            unregisterReceiver();
            mRoomPresenter.onDestory();
            mEnterRoomHelper.onDestory();
            QavsdkControl.getInstance().clearVideoMembers();
            QavsdkControl.getInstance().onDestroy();
            mDefaultUEH.uncaughtException(thread, ex); // 不加本语句会导致ANR
        }

    }

}
